package com.sisgesbyte.services.proyeccion;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.inject.Inject;

import com.sisgesbyte.common.ConstModAdministracion;
import com.sisgesbyte.common.ConstProyeccion;
import com.sisgesbyte.common.ConstantesInternasSistema;
import com.sisgesbyte.common.Validaciones;
import com.sisgesbyte.dao.administracion.MantCategoriaProductoDao;
import com.sisgesbyte.dao.administracion.MantenimientoMarcaDao;
import com.sisgesbyte.dao.beanDao.FiltrosBean;
import com.sisgesbyte.dao.beanDao.FiltrosSQLBean;
import com.sisgesbyte.dao.beanDao.ProyProductoPeriodoRequest;
import com.sisgesbyte.dao.proyeccion.MantProyeccionProductoPeriodoDao;
import com.sisgesbyte.data.entity.administracion.CategoriaProductoEntity;
import com.sisgesbyte.data.entity.administracion.MarcaEntity;
import com.sisgesbyte.data.entity.comun.GenericEntity;
import com.sisgesbyte.data.entity.proyeccion.ProyeccionProductoPeriodoEntity;
import com.sisgesbyte.services.commonBean.GenericResponse;
import com.sisgesbyte.services.proyeccion.bean.ListaProyGeneralCategoriaResponse;
import com.sisgesbyte.services.proyeccion.bean.ListaProyGeneralMarcasResponse;
import com.sisgesbyte.services.proyeccion.bean.ListaProyProductosPeriodoResponse;
import com.sisgesbyte.services.proyeccion.bean.ProyGeneralCategoriaBean;
import com.sisgesbyte.services.proyeccion.bean.ProyProductoPeriodoBean;
import com.sisgesbyte.services.proyeccion.bean.ProyeccionGeneralMarcasBean;

@Stateless
public class MantProyeccionPeriodoServiceImpl implements
		MantProyeccionPeriodoService {

	@EJB
	private MantProyeccionProductoPeriodoDao mantProyeccionProductoPeriodoDao;
	@EJB
	private MantProyeccionMontoPeriodoService mantProyeccionMontoPeriodoService;
	@EJB
	private MantenimientoMarcaDao mantenimientoMarcaDao;
	@EJB
	private MantCategoriaProductoDao mantCategoriaProductoDao;
	private List<CategoriaProductoEntity> listaHijosCategoriaProd;
	private List<CategoriaProductoEntity> hijos;
	@Inject
	private Validaciones validaciones;

	@Override
	public ListaProyProductosPeriodoResponse listaProyeccionPeriodo(
			String codTransaccion, int idPeriodo, String buscar) {

		String mensajeTransaccionMetodo = "[listaProyeccionPeriodo idTx="
				+ codTransaccion + "] - ";
		ListaProyProductosPeriodoResponse response = new ListaProyProductosPeriodoResponse();

		List<ProyeccionProductoPeriodoEntity> responseDao = null;
		try {
			FiltrosSQLBean filtroSQL = new FiltrosSQLBean();
			List<Object> valores = new ArrayList<>();
			List<FiltrosBean> filtro = new ArrayList<FiltrosBean>();

			// filtro por periodo
			if (idPeriodo > 0) {
				FiltrosBean listaPeriodo = new FiltrosBean();
				List<String> campoPeriodo = new ArrayList<String>();
				campoPeriodo.add("ppp.periodo_id");
				listaPeriodo.setCampos(campoPeriodo);
				listaPeriodo.setOperador("=");
				filtro.add(listaPeriodo);
				valores.add(idPeriodo);
			}
			// -------------------
			// filtro por String
			if (buscar != null && buscar.trim().length() > 0) {
				FiltrosBean listaCampo = new FiltrosBean();
				List<String> campo = new ArrayList<String>();
				campo.add("ppp.id");
				campo.add("m.marca");
				campo.add("p.cod_prod");
				campo.add("p.producto");
				campo.add("cp.nombre");
				listaCampo.setCampos(campo);
				listaCampo.setOperador("like");
				filtro.add(listaCampo);
				filtroSQL.setListaFiltros(filtro);
				valores.add("%" + buscar + "%");
			}
			// -------------------

			filtroSQL.setListaFiltros(filtro);
			filtroSQL.setListaValores(valores);

			responseDao = mantProyeccionProductoPeriodoDao.listaProyeccionProductoPeriodo(filtroSQL);
		} catch (Exception e) {
			System.out.println(mensajeTransaccionMetodo+ "Hubo un error al listar de  BD " + e);
			response.setCodigoRespuesta(ConstProyeccion.PROYECCION_LISTAR_COD_IDT);
			response.setMensajeRespuesta(ConstProyeccion.PROYECCION_LISTAR_MSJ_IDT);
			return response;
		}

		if (responseDao.size() > 0) {
			List<ProyProductoPeriodoBean> listaProy = new ArrayList<ProyProductoPeriodoBean>();
				
			for (ProyeccionProductoPeriodoEntity ls : responseDao) {
				ProyProductoPeriodoBean bean = new ProyProductoPeriodoBean();
				bean.setCantidadProyectada(ls.getCantidad_proyectada());
				bean.setCategoriaProductoId(ls.getCategoria_producto_id());
				bean.setCategoria(validaciones.validarCamposString(ls.getCategoria()));
				bean.setCodigoBanda(validaciones.validarCamposString(ls.getCodigo_banda()));
				bean.setCodProd(validaciones.validarCamposString(ls.getCod_prod()));
				bean.setId(ls.getId());
				bean.setMarca(validaciones.validarCamposString(ls.getMarca()));
				bean.setMarcaId(ls.getMarca_id());
				bean.setPeriodoId(ls.getPeriodo_id());
				bean.setProducto(validaciones.validarCamposString(ls.getProducto()));
				bean.setPrecioPromedio(ls.getPrecio_promedio());
				bean.setProductoId(ls.getProducto_id());
				listaProy.add(bean);
			}
			response.setIdTransaccion(codTransaccion);
			response.setCodigoRespuesta(ConstantesInternasSistema.CODIGO_EXITO);
			response.setMensajeRespuesta(ConstantesInternasSistema.MENSAJE_EXITO);
			response.setListaProyeccionPeriodo(listaProy);
		} else {
			response.setIdTransaccion(codTransaccion);
			response.setCodigoRespuesta(ConstProyeccion.PROYECCION_LISTAR_COD_IDF);
			response.setMensajeRespuesta(ConstProyeccion.PROYECCION_LISTAR_MSJ_IDF);
		}

		return response;
	}

	@Override
	public GenericResponse nuevaProyeccionPeriodo(String codTransaccion,
			ProyProductoPeriodoBean request) {
		String mensajeTransaccionMetodo = "[nuevaProyeccionPeriodo idTx=" + codTransaccion + "] - ";
		GenericResponse response = new GenericResponse();
		GenericEntity responseDao = null;
		try {
			ProyProductoPeriodoRequest req = new ProyProductoPeriodoRequest();
			req.setIdProducto(request.getProductoId());
			req.setIdPeriodo(request.getPeriodoId());
			req.setCodigoBanda(validaciones.validarCamposString(request.getCodigoBanda()));
			req.setCantidadProyectada(request.getCantidadProyectada());

			responseDao = mantProyeccionProductoPeriodoDao.guardarProyeccionPeriodo(req);

			if (responseDao.getCod_error() == Integer.parseInt(ConstantesInternasSistema.CODIGO_EXITO)) {
				response.setCodigoRespuesta(ConstantesInternasSistema.CODIGO_EXITO);
				response.setMensajeRespuesta(ConstantesInternasSistema.MENSAJE_EXITO);
				
				try{
					//actualizamos el monto del periodo
					GenericResponse actualizar = mantProyeccionMontoPeriodoService.actualizarMontoProyeccionPeriodo(codTransaccion, request.getPeriodoId());
					if(actualizar.getCodigoRespuesta().equalsIgnoreCase(ConstantesInternasSistema.CODIGO_EXITO)){
						System.out.println("Se actualizo el monto del periodo");
					}else{
						System.out.println("Error al actualizar monto del periodo " + actualizar.getCodigoRespuesta());
					}
				}catch(Exception e){
					System.out.println("Error Tecnico al actualizar los el monto del periodo");
				}
				
			} else {
				response.setCodigoRespuesta(String.valueOf(responseDao.getCod_error()));
				response.setMensajeRespuesta(responseDao.getMsj_error());
			}
		} catch (Exception e) {
			System.out.println(mensajeTransaccionMetodo+ "Hubo un error al registrar la Proyeccion en BD " + e);
			response.setCodigoRespuesta(ConstModAdministracion.MANT_NUEVO_COD_IDT);
			response.setMensajeRespuesta(ConstModAdministracion.MANT_NUEVO_MSJ_IDT.replace("msj", mensajeTransaccionMetodo));
		}
		return response;
	}

	@Override
	public GenericResponse editarProyeccionPeriodo(String codTransaccion,
			ProyProductoPeriodoBean request) {
		String mensajeTransaccionMetodo = "[editarProyeccionPeriodo idTx=" + codTransaccion + "] - ";
		GenericResponse response = new GenericResponse();
		GenericEntity responseDao = null;
		try {
			ProyProductoPeriodoRequest req = new ProyProductoPeriodoRequest();
			req.setId(request.getId());
			req.setIdPeriodo(request.getPeriodoId());
			req.setIdProducto(request.getProductoId());
			req.setCodigoBanda(validaciones.validarCamposString(request.getCodigoBanda()));
			req.setCantidadProyectada(request.getCantidadProyectada());

			responseDao = mantProyeccionProductoPeriodoDao.actualizarProyeccionPeriodo(req);

			if (responseDao.getCod_error() == Integer.valueOf(ConstantesInternasSistema.CODIGO_EXITO)) {
				
				response.setCodigoRespuesta(ConstantesInternasSistema.CODIGO_EXITO);
				response.setMensajeRespuesta(ConstantesInternasSistema.MENSAJE_EXITO);
				
				try{
					//actualizamos el monto del periodo
					GenericResponse actualizar = mantProyeccionMontoPeriodoService.actualizarMontoProyeccionPeriodo(codTransaccion, request.getPeriodoId());
					if(actualizar.getCodigoRespuesta().equalsIgnoreCase(ConstantesInternasSistema.CODIGO_EXITO)){
						System.out.println("Se actualizo el monto del periodo");
					}else{
						System.out.println("Error al actualizar monto del periodo " + actualizar.getCodigoRespuesta());
					}
				}catch(Exception e){
					System.out.println("Error Tecnico al actualizar los el monto del periodo");
				}
			} else {
				response.setCodigoRespuesta(String.valueOf(responseDao.getCod_error()));
				response.setMensajeRespuesta(responseDao.getMsj_error());
			}

		} catch (Exception e) {
			System.out.println(mensajeTransaccionMetodo+ "Hubo un error al editar  en BD " + e);
			response.setCodigoRespuesta(ConstModAdministracion.MANT_EDITAR_COD_IDT);
			response.setMensajeRespuesta(ConstModAdministracion.MANT_EDITAR_MSJ_IDT.replace("msj", mensajeTransaccionMetodo));
		}
		return response;
	}

	@Override
	public GenericResponse deleteProyeccionPeriodo(String codTransaccion,
			int codProyeccion) {

		String mensajeTransaccionMetodo = "[deleteProyeccionPeriodo idTx="
				+ codTransaccion + "] - ";
		GenericResponse response = new GenericResponse();
		GenericEntity responseDao = null;
		try {
			responseDao = mantProyeccionProductoPeriodoDao.eliminarProyeccionPeriodo(codProyeccion);
			if (responseDao.getCod_error() == Integer.valueOf(ConstantesInternasSistema.CODIGO_EXITO)) {
				response.setCodigoRespuesta(ConstantesInternasSistema.CODIGO_EXITO);
				response.setMensajeRespuesta(ConstantesInternasSistema.MENSAJE_EXITO);
			} else {
				response.setCodigoRespuesta(String.valueOf(responseDao.getCod_error()));
				response.setMensajeRespuesta(responseDao.getMsj_error());
			}
		} catch (Exception e) {
			System.out.println(mensajeTransaccionMetodo+ "Hubo un error al eliminar  en BD " + e);
			response.setCodigoRespuesta(ConstModAdministracion.MANT_EDITAR_COD_IDT);
			response.setMensajeRespuesta(ConstModAdministracion.MANT_EDITAR_MSJ_IDT.replace("msj", mensajeTransaccionMetodo));
		}
		return response;
	}

	@Override
	public ListaProyGeneralMarcasResponse mostrarProyPeriodoMarcas(
			String codTransaccion, int idPeriodo) {
		String mensajeTransaccionMetodo = "[mostrarProyGeneralMarcas idTx=" + codTransaccion + "] - ";
		
		ListaProyGeneralMarcasResponse response = new ListaProyGeneralMarcasResponse();
		
		if(idPeriodo < 1){
			System.out.println("Seleccionar periodo ");
			response.setIdTransaccion(codTransaccion);
			response.setCodigoRespuesta(ConstProyeccion.PROYECCION_LISTAR_COD_IDF);
			response.setMensajeRespuesta(ConstProyeccion.PROYECCION_LISTAR_MSJ_IDF);
			return response;
		}
		ListaProyProductosPeriodoResponse listaPeriodo =null;
		try{
			//1.- cargamos la lista de proyeccion del periodo seleccionado
			listaPeriodo = listaProyeccionPeriodo(codTransaccion,idPeriodo, null);
		}catch(Exception e){
			response.setCodigoRespuesta(ConstProyeccion.PROYECCION_LISTAR_COD_IDT);
			response.setMensajeRespuesta(ConstProyeccion.PROYECCION_LISTAR_MSJ_IDT);
			return response;
		}
		List<MarcaEntity> marcasDao = null;
		try{
			//2.- obtenemos la lista de marcas de productos
			marcasDao = mantenimientoMarcaDao.listaMarcas(null);
		}catch(Exception e){
			System.out.println(mensajeTransaccionMetodo + "Hubo un error al listar la lista de marcas de productos de  BD " + e);
			response.setCodigoRespuesta(ConstProyeccion.PROYECCION_LISTAR_COD_IDT);
			response.setMensajeRespuesta(ConstProyeccion.PROYECCION_LISTAR_MSJ_IDT);
			return response;
		}
		
		List<ProyeccionGeneralMarcasBean> listaMarcasProy = new ArrayList<ProyeccionGeneralMarcasBean>();
		for(MarcaEntity marca : marcasDao){
			ProyeccionGeneralMarcasBean bean = new ProyeccionGeneralMarcasBean();
			bean.setIdMarca(marca.getId());
			bean.setMarca(validaciones.validarCamposString(marca.getMarca()));
			BigDecimal total = BigDecimal.ZERO;
			for(ProyProductoPeriodoBean proy : listaPeriodo.getListaProyeccionPeriodo()){
				if(marca.getId() == proy.getMarcaId()){
					try{
						total = total.add(proy.getCantidadProyectada().multiply(proy.getPrecioPromedio()));
					}catch(Exception e){
						total = BigDecimal.ZERO;
						System.out.println("Error al obtener el monto de la proyeccion del producto " + e.getMessage());
					}
				}
			}
			bean.setMontoTotal(total);
			if(total.compareTo(BigDecimal.ZERO) > 0){
				listaMarcasProy.add(bean);
			}
		}
		if (listaMarcasProy.size() > 0) {
			response.setCodigoRespuesta(ConstantesInternasSistema.CODIGO_EXITO);
			response.setMensajeRespuesta(ConstantesInternasSistema.MENSAJE_EXITO);
			response.setListaProyeccionGeneralMarcas(listaMarcasProy);
		} else {
			response.setCodigoRespuesta(ConstModAdministracion.MANT_ELIMINAR_COD_IDF);
			response.setMensajeRespuesta(ConstModAdministracion.MANT_ELIMINAR_MSJ_IDF.replace("msj", mensajeTransaccionMetodo));
		}
		return response;
	}

	@Override
	public ListaProyGeneralCategoriaResponse mostrarProyPeriodoCategoria(
			String codTransaccion, int idPeriodo) {
		String mensajeTransaccionMetodo = "[mostrarProyPeriodoCategoria idTx=" + codTransaccion + "] - ";
		
		ListaProyGeneralCategoriaResponse response = new ListaProyGeneralCategoriaResponse();
		if(idPeriodo < 1){
			System.out.println("Seleccionar periodo ");
			response.setIdTransaccion(codTransaccion);
			response.setCodigoRespuesta(ConstProyeccion.PROYECCION_LISTAR_COD_IDF);
			response.setMensajeRespuesta(ConstProyeccion.PROYECCION_LISTAR_MSJ_IDF);
			return response;
		}
		ListaProyProductosPeriodoResponse listaPeriodo =null;
		try{
			//1.- cargamos la lista de proyeccion del periodo seleccionado
			listaPeriodo = listaProyeccionPeriodo(codTransaccion,idPeriodo, null);
		}catch(Exception e){
			response.setCodigoRespuesta(ConstProyeccion.PROYECCION_LISTAR_COD_IDT);
			response.setMensajeRespuesta(ConstProyeccion.PROYECCION_LISTAR_MSJ_IDT);
			return response;
		}
		List<CategoriaProductoEntity> listaCategoriaProd = null;
		try{
			
			//2.- obtenemos la lista de categoria de productos
			listaCategoriaProd = mantCategoriaProductoDao.listarCategoriasProd(null);
			this.listaHijosCategoriaProd = listaCategoriaProd;
		}catch(Exception e){
			System.out.println(mensajeTransaccionMetodo + "Hubo un error al listar las proyecciones de categorias productos de  BD " + e);
			response.setCodigoRespuesta(ConstProyeccion.PROYECCION_LISTAR_COD_IDT);
			response.setMensajeRespuesta(ConstProyeccion.PROYECCION_LISTAR_MSJ_IDT);
			return response;
		}
		List<ProyGeneralCategoriaBean> listaCategoriaProy = new ArrayList<ProyGeneralCategoriaBean>();
		for(CategoriaProductoEntity categoria : listaCategoriaProd){
			ProyGeneralCategoriaBean bean = new ProyGeneralCategoriaBean();
			bean.setId(categoria.getId());
			bean.setCategoria(categoria.getNombre());
			bean.setIdPadre(categoria.getPadre_id());
			
			hijos = new ArrayList<CategoriaProductoEntity>();
			//agregamos al padre
			hijos.add(categoria);
			//buscamos sus hijos
			capturarHijos(categoria.getId());
			//buscamos los montos de todos sus hijos
			BigDecimal total = BigDecimal.ZERO;
			for(CategoriaProductoEntity h :hijos){
				for(ProyProductoPeriodoBean proy : listaPeriodo.getListaProyeccionPeriodo()){
					if(h.getId() == proy.getCategoriaProductoId()){
						total =total.add(proy.getPrecioPromedio().multiply(proy.getCantidadProyectada()));
					}
				}
			}
			
			bean.setMontoTotal(total);
			
			if(total.compareTo(BigDecimal.ZERO) > 0){
				listaCategoriaProy.add(bean);
			}
		}

		if (listaCategoriaProy.size() > 0) {
			response.setCodigoRespuesta(ConstantesInternasSistema.CODIGO_EXITO);
			response.setMensajeRespuesta(ConstantesInternasSistema.MENSAJE_EXITO);
			response.setListaProyGeneralCategoria(listaCategoriaProy);
		} else {
			response.setCodigoRespuesta(ConstModAdministracion.MANT_ELIMINAR_COD_IDF);
			response.setMensajeRespuesta(ConstModAdministracion.MANT_ELIMINAR_MSJ_IDF.replace("msj", mensajeTransaccionMetodo));
		}
		return response;
	}
	public void capturarHijos(int idPadre){
		for(CategoriaProductoEntity hijo :listaHijosCategoriaProd){
			if(idPadre == hijo.getPadre_id()){
				hijos.add(hijo);
				capturarHijos(hijo.getId());
			}
		}
	}
}
